{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from matplotlib import rc, rcParams\n",
    "rc('axes', linewidth=5)\n",
    "\n",
    "from remat.core.dfgraph import gen_linear_graph\n",
    "from experiments.common.load_keras_model import get_keras_model\n",
    "from remat.core.solvers.strategy_checkpoint_all import solve_checkpoint_all\n",
    "from remat.tensorflow2.extraction import dfgraph_from_keras\n",
    "from remat.core.solvers.strategy_chen import solve_chen_sqrtn, solve_chen_greedy\n",
    "from remat.core.solvers.strategy_optimal_ilp import solve_ilp_gurobi\n",
    "from remat.core.solvers.strategy_griewank import solve_griewank\n",
    "\n",
    "sns.set('talk')\n",
    "sns.set_style('white')\n",
    "RED = \"#e74c3c\"\n",
    "BLUE = \"#3498db\"\n",
    "flatui = [RED, BLUE, \"#95a5a6\", \"#e74c3c\", \"#34495e\", \"#2ecc71\"]\n",
    "sns.set_palette(flatui)\n",
    "\n",
    "g = gen_linear_graph(32)\n",
    "scheduler_result_all = solve_checkpoint_all(g)\n",
    "scheduler_result = solve_griewank(g, 7)\n",
    "\n",
    "data = []\n",
    "compute_so_far = 0\n",
    "for idx, (mem_step, sched_item) in enumerate(zip(scheduler_result_all.schedule_aux_data.mem_timeline, scheduler_result_all.schedule)):\n",
    "    if 'OperatorEvaluation' in str(type(sched_item)):\n",
    "        compute_so_far += sched_item.operator_cost\n",
    "        data.append({'Time': compute_so_far, 'Solver': 'Retain all\\nactivations', 'Total memory consumed': (mem_step - g.cost_ram_fixed) * 0.85})\n",
    "data.pop()\n",
    "data.append({'Time': compute_so_far + 15, 'Solver': 'Retain all\\nactivations', 'Total memory consumed': data[-1]['Total memory consumed']})\n",
    "no_remat_done_timestep = compute_so_far + 15    \n",
    "    \n",
    "from collections import defaultdict\n",
    "when_computed = defaultdict(list)\n",
    "for idx, sched_item in enumerate(scheduler_result.schedule):\n",
    "    if 'OperatorEvaluation' in str(type(sched_item)):\n",
    "        when_computed[sched_item.id].append(idx)\n",
    "        \n",
    "compute_so_far = 0\n",
    "remat_cpu_range = []\n",
    "remat_is_rematerialized = []\n",
    "remat_ram_range = []\n",
    "for idx, (mem_step, sched_item) in enumerate(zip(scheduler_result.schedule_aux_data.mem_timeline, scheduler_result.schedule)):\n",
    "    if 'OperatorEvaluation' in str(type(sched_item)):\n",
    "        compute_so_far += sched_item.operator_cost\n",
    "        data.append({'Time': compute_so_far, 'Solver': 'Rematerialize\\nactivations', 'Total memory consumed': mem_step - g.cost_ram_fixed})\n",
    "        remat_is_rematerialized.append(idx != when_computed[sched_item.id][0])\n",
    "        remat_cpu_range.append(compute_so_far)\n",
    "        remat_ram_range.append(mem_step - g.cost_ram_fixed)\n",
    "remat_done_timestep = compute_so_far\n",
    "df = pd.DataFrame(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 360x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(5, 5))\n",
    "plot = sns.lineplot(x='Time', y='Total memory consumed', hue='Solver', data=df)\n",
    "\n",
    "plt.axvline(no_remat_done_timestep, color=RED, linestyle='dotted', alpha=0.7, linewidth=3)\n",
    "plt.axvline(remat_done_timestep, color=BLUE, linestyle='dotted', alpha=0.7, linewidth=3)\n",
    "\n",
    "ax = plot.axes\n",
    "ax.margins(x=0, y=0)\n",
    "ax.set_xlim(0, 115)\n",
    "ax.set_ylim(0, 38)\n",
    "\n",
    "ax.fill_between(remat_cpu_range, 0, remat_ram_range, where=remat_is_rematerialized, facecolor='#3498db', alpha=0.5)\n",
    "sns.despine()\n",
    "handles, labels = ax.get_legend_handles_labels()\n",
    "box = ax.get_position()\n",
    "ax.set_position([box.x0, box.y0 + box.height * 0.1,\n",
    "                 box.width, box.height * 0.9])\n",
    "plt.legend(loc='best', fancybox=False, title=None, frameon=False, handles=handles[1:], labels=labels[1:],\n",
    "          ncol=2, bbox_to_anchor=(1.075, -0.2))\n",
    "plt.savefig('timeline.pdf', bbox_inches='tight')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x216 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.rcParams['axes.labelweight'] = 'bold'\n",
    "plt.rcParams['axes.labelsize'] = '18'\n",
    "\n",
    "plt.figure(figsize=(6, 3))\n",
    "plot = sns.lineplot(x='Time', y='Total memory consumed', hue='Solver', data=df)\n",
    "plt.ylabel(\"RAM used (GB)\")\n",
    "plt.xlabel(\"Time\", labelpad=5)\n",
    "plt.axvline(no_remat_done_timestep, color=RED, linestyle='dotted', alpha=0.7, linewidth=3)\n",
    "plt.axvline(remat_done_timestep, color=BLUE, linestyle='dotted', alpha=0.7, linewidth=3)\n",
    "\n",
    "ax = plot.axes\n",
    "ax.margins(x=0, y=0)\n",
    "ax.set_xlim(0, 115)\n",
    "ax.set_ylim(0, 30)\n",
    "plt.xticks([])\n",
    "\n",
    "ax.fill_between(remat_cpu_range, 0, remat_ram_range, where=remat_is_rematerialized, facecolor='#3498db', alpha=0.5)\n",
    "sns.despine()\n",
    "handles, labels = ax.get_legend_handles_labels()\n",
    "box = ax.get_position()\n",
    "ax.set_position([box.x0, box.y0 + box.height * 0.1,\n",
    "                 box.width, box.height * 0.9])\n",
    "plt.legend(loc='best', fancybox=False, title=None, frameon=False, handles=handles[1:], labels=labels[1:],\n",
    "          ncol=2, bbox_to_anchor=(.99, -0.12), borderpad=0)\n",
    "plt.margins(0,0)\n",
    "plt.savefig('timeline.pdf', bbox_inches='tight', pad_inches=0)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
